﻿using Newtonsoft.Json;
using PSDLib.Models;
using PSDLib.Protocols;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PSDLib
{
    public static class PSDFunction
    {
        static string[] size_unit = new string[] { "B", "KB", "MB", "GB", "TB", "PB" };
        public static string FormatByteSize(double size)
        {
            string text = "";

            for (int i = 1; i <= size_unit.Length; i++)
            {
                if (size / Math.Pow(1024, i) < 1)
                {
                    text = Math.Round(size / Math.Pow(1024, i - 1), 2).ToString() + " " + size_unit[i - 1];
                    break;
                }
            }

            return text;
        }

        public static bool GetLocalStorage(dl_download_device device)
        {
            bool changed = false;

            var storageList = new List<StorageInfo>();

            string[] exclude_volumne = System.Configuration.ConfigurationManager.AppSettings["ExcludeVolumeName"].Split(",".ToCharArray());

            try
            {
                SelectQuery selectQuery = new SelectQuery("select * from win32_logicaldisk");

                ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery);

                ManagementObjectCollection diskcollection = searcher.Get();
                if (diskcollection != null && diskcollection.Count > 0)
                {
                    foreach (ManagementObject disk in diskcollection)
                    {
                        int nType = Convert.ToInt32(disk["DriveType"]);
                        if (nType == Convert.ToInt32(DriveType.Fixed))
                        {
                            if (!exclude_volumne.Contains(disk["VolumeName"].ToString()))
                            {
                                StorageInfo diskInfo = new StorageInfo();
                                diskInfo.DiskDriver = disk["DeviceID"].ToString();
                                diskInfo.VolumeName = disk["VolumeName"].ToString();
                                diskInfo.SumSpace = Convert.ToDouble(disk["Size"]);
                                diskInfo.FreeSpace = Convert.ToDouble(disk["FreeSpace"]);
                                diskInfo.StorageType = GetStorageType(device, diskInfo.DiskDriver);
                                storageList.Add(diskInfo);

                                CopySmartPlayer(diskInfo);
                            }
                        }
                        //else if (nType == Convert.ToInt32(DriveType.CDRom))
                        //{
                        //CDRom cd = new CDRom();
                        //PSDClient.palDisk.Controls.Add(cd);
                        //cd.Dock = DockStyle.Left;
                        //cd.BringToFront();
                        //cd.DiskDriver = disk["DeviceID"].ToString();
                        //cd.VolumeName = disk["Description"].ToString();
                        //CDRomList.Add(cd);
                        //}
                    }

                    foreach (var storage in device.StorageList)
                    {
                        if (storageList.Where(t => t.DiskDriver == storage.storage_driver).FirstOrDefault() == null)
                        {
                            storage.state = -1;
                            changed = false;
                        }
                    }

                    foreach (var st in storageList)
                    {
                        var storage = device.StorageList.Where(t => t.storage_driver == st.DiskDriver).FirstOrDefault();

                        if (storage == null)
                        {
                            storage = new dl_download_device_storage();
                            device.StorageList.Add(storage);
                            storage.id = Guid.NewGuid().ToString();
                            storage.device_id = device.id;
                            storage.storage_driver = st.DiskDriver;
                            storage.storage_type = -1;
                            storage.storage_group = 0;
                            storage.state = 0;
                            changed = true;
                        }

                        storage.storage_name = st.VolumeName.ToString();
                        storage.storage_total_size = st.SumSpace;
                        storage.storage_free_size = st.FreeSpace;
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " GetLocalStorage " + ex.Message);
            }

            return changed;
        }

        private static void CopySmartPlayer(StorageInfo storage)
        {
            string player = "SmartPlayer-Win32-Setup.exe";
            string dest = System.IO.Path.Combine(storage.DiskDriver, player);

            if (!System.IO.File.Exists(dest))
            {
                string src = System.IO.Path.Combine(Application.StartupPath, player);

                if (System.IO.File.Exists(src))
                {
                    System.IO.File.Copy(src, dest, true);
                }
            }
        }


        public static void UpdateLocalStorage(dl_download_device device)
        {
            try
            {
                SelectQuery selectQuery = new SelectQuery("select * from win32_logicaldisk");

                ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery);

                ManagementObjectCollection diskcollection = searcher.Get();

                foreach (ManagementObject disk in diskcollection)
                {
                    var d = device.StorageList.Where(t => t.storage_driver == disk["DeviceID"].ToString()).FirstOrDefault();

                    if (d != null)
                    {
                        d.storage_total_size = Convert.ToDouble(disk["Size"]);
                        d.storage_free_size = Convert.ToDouble(disk["FreeSpace"]);

                        //if (device.main_storage == disk["DeviceID"].ToString())
                        //{
                        //    device.main_storage_total = d.SumSpace;
                        //    device.main_storage_free = d.FreeSpace;
                        //}
                        //else if (device.second_storage == disk["DeviceID"].ToString())
                        //{
                        //    device.second_storage_total = d.SumSpace;
                        //    device.second_storage_free = d.FreeSpace;
                        //}
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString() + " UpdateLocalStorage " + ex.Message);
            }
        }

        public static int GetStorageType(dl_download_device device, string partitionName)
        {
            if (device != null)
            {
                if (partitionName == device.main_storage)
                {
                    return 1;
                }
                else if (partitionName == device.second_storage)
                {
                    return 2;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }

        public static bool TestConnection(IPEndPoint localEP, IPEndPoint tcpServerEP)
        {
            TcpClient client = new TcpClient(localEP);

            bool testResult = false;
            Thread testThread = new Thread(new ThreadStart(delegate ()
            {
                try
                {
                    client.Connect(tcpServerEP);
                    var testMsg = new TestConnectionMessage();
                    testMsg.IP = localEP.Address.ToString();
                    testMsg.Port = localEP.Port;
                    var outputBuffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(testMsg));
                    var ns = client.GetStream();
                    ns.Write(outputBuffer, 0, outputBuffer.Length);
                    ns.Write(new byte[] { 0 }, 0, 1);
                    var recvBuffer = new byte[10];
                    client.Client.Receive(recvBuffer);
                    string result = Encoding.UTF8.GetString(recvBuffer).Replace("\0", "");
                    testResult = (result == "success");
                }
                catch (Exception ex)
                { }
            }));

            testThread.Start();

            int timeout = 0;
            while (timeout <= 5 && !testResult)
            {
                timeout += 1;
                Thread.Sleep(1000);
                Application.DoEvents();
            }

            try
            {
                testThread.Abort();
            }
            catch { }

            client.Close();

            return testResult;
        }
    }
}
